home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / tex / dvi / dvipssrc.zoo / loadfont.c < prev    next >
C/C++ Source or Header  |  1991-01-13  |  10KB  |  364 lines

  1. /*
  2.  *   Here's the code to load a PK file into memory.
  3.  *   Individual bitmaps won't be unpacked until they prove to be needed.
  4.  */
  5. #include "structures.h" /* The copyright notice in that file is included too! */
  6. /*
  7.  *   These are the external routines we use.
  8.  */
  9. extern void makefont() ;
  10. extern void error() ;
  11. extern integer scalewidth() ;
  12. extern void tfmload() ;
  13. extern FILE *pksearch() ;
  14. /*
  15.  *   These are the external variables we use.
  16.  */
  17. #ifdef DEBUG
  18. extern integer debug_flag;
  19. #endif  /* DEBUG */
  20. extern long bytesleft ;
  21. extern quarterword *raster ;
  22. extern int actualdpi ;
  23. extern real alpha ;
  24. extern char *pkpath ;
  25. char errbuf[200] ;
  26. int lastresortsizes[40] ;
  27. extern integer fsizetol ;
  28. extern Boolean nosmallchars ;
  29. #ifdef FONTLIB
  30. extern Boolean flib ;
  31. extern FILE *flisearch() ;
  32. #endif
  33. /*
  34.  *   We use malloc here.
  35.  */
  36. char *malloc() ;
  37.  
  38. /*
  39.  *   Now we have some routines to get stuff from the PK file.
  40.  *   Subroutine pkbyte returns the next byte.
  41.  */
  42.  
  43. FILE *pkfile ;
  44. char name[50] ;
  45. void
  46. badpk(s)
  47.    char *s ;
  48. {
  49.    (void)sprintf(errbuf,"! Bad PK file %s: %s",name,s) ;
  50.    error(errbuf);
  51. }
  52.  
  53. shalfword
  54. pkbyte()
  55. {
  56.    register shalfword i ;
  57.  
  58.    if ((i=getc(pkfile))==EOF)
  59.       badpk("unexpected eof") ;
  60.    return(i) ;
  61. }
  62.  
  63. integer
  64. pkquad()
  65. {
  66.    register integer i ;
  67.  
  68.    i = pkbyte() ;
  69.    if (i > 127)
  70.       i -= 256 ;
  71.    i = i * 256 + pkbyte() ;
  72.    i = i * 256 + pkbyte() ;
  73.    i = i * 256 + pkbyte() ;
  74.    return(i) ;
  75. }
  76.  
  77. integer
  78. pktrio()
  79. {
  80.    register integer i ;
  81.  
  82.    i = pkbyte() ;
  83.    i = i * 256 + pkbyte() ;
  84.    i = i * 256 + pkbyte() ;
  85.    return(i) ;
  86. }
  87.  
  88.  
  89. /*
  90.  *   pkopen opens the pk file.  This is system dependent.  We work really
  91.  *   hard to open some sort of PK file.
  92.  */
  93. int dontmakefont = 0 ; /* if makefont fails once we won't try again */
  94.  
  95. void
  96. lectureuser() {
  97.    static int userwarned = 0 ;
  98.  
  99.    if (! userwarned) {
  100.       error("Such scaling will generate extremely poor output.") ;
  101.       userwarned = 1 ;
  102.    }
  103. }
  104. Boolean
  105. pkopen(fd)
  106.         register fontdesctype *fd ;
  107. {
  108.    register char *d, *n ;
  109.  
  110.    d = fd->area ;
  111.    n = fd->name ;
  112.    if (*d==0)
  113.       d = pkpath ;
  114. #ifdef FONTLIB
  115.    if (*(fd->area) == 0) { 
  116.       int del ;
  117.       for (del=0; del<=RES_TOLERANCE(fd->dpi); del=del>0?-del:-del+1) {
  118.         if ((pkfile=flisearch(n, fd->dpi + del)) != (FILE *)NULL )
  119.           return(1);
  120.       }
  121.    }
  122. #endif
  123.    {  
  124.       int del ;
  125.       for (del=0; del<=RES_TOLERANCE(fd->dpi); del=del>0?-del:-del+1) {
  126.          (void)sprintf(name, "%s.%dpk", n, fd->dpi + del) ;
  127.          if (pkfile=pksearch(d, name, READBIN, n, fd->dpi + del))
  128.             return(1) ;
  129.       }
  130.    }
  131.    if (d == pkpath && dontmakefont == 0) {
  132.       (void)sprintf(name, "%s.%dpk", n, fd->dpi) ;
  133.       makefont(n, (int)fd->dpi, DPI) ;
  134.       if (pkfile = pksearch(d, name, READBIN, n, fd->dpi))
  135.          return(1) ;
  136. #ifndef MSDOS
  137.       dontmakefont = 1 ;
  138. #endif
  139.    }
  140. /*
  141.  *   If nothing above worked, then we get desparate.  We attempt to
  142.  *   open the stupid font at one of a small set of predefined sizes,
  143.  *   and then use PostScript scaling to generate the correct size.
  144.  *
  145.  *   We much prefer scaling up to scaling down, since scaling down
  146.  *   can omit character features, so we try the larger sizes first,
  147.  *   and then work down.
  148.  */
  149.    {
  150.       int i, j ;
  151.  
  152.       if (lastresortsizes[0] && fd->dpi < 30000) {
  153.          for (i=0; lastresortsizes[i] < fd->dpi; i++) ;
  154.          for (j = i-1; j >= 0; j--) {
  155.             (void)sprintf(name, "%s.%dpk", n, lastresortsizes[j]) ;
  156. #ifdef FONTLIB
  157.             if ((pkfile=flisearch(n,(halfword)lastresortsizes[j]))
  158.              || (pkfile=pksearch(d, name, READBIN, n,
  159.                          (halfword)lastresortsizes[j]))) {
  160. #else
  161.             if (pkfile=pksearch(d, name, READBIN, n,
  162.                                            (halfword)lastresortsizes[j])) {
  163. #endif
  164.                fd->loadeddpi = lastresortsizes[j] ;
  165.                fd->alreadyscaled = 0 ;
  166.                (void)sprintf(errbuf,
  167.                        "Font %s at %d not found; scaling %d instead.",
  168.                                          name, fd->dpi, lastresortsizes[j]) ;
  169.                error(errbuf) ;
  170.                lectureuser() ;
  171.                return 1 ;
  172.             }
  173.          }
  174.          for (j = i; lastresortsizes[j] < 30000; j++) {
  175.             (void)sprintf(name, "%s.%dpk", n, lastresortsizes[j]) ;
  176. #ifdef FONTLIB
  177.             if ((pkfile=flisearch(n, (halfword)lastresortsizes[j]))
  178.                 || (pkfile=pksearch(d, name, READBIN, n,
  179.                       (halfword)lastresortsizes[j]))) {
  180. #else
  181.             if (pkfile=pksearch(d, name, READBIN, n, 
  182.                                        (halfword)lastresortsizes[j])) {
  183. #endif
  184.                fd->loadeddpi = lastresortsizes[j] ;
  185.                fd->alreadyscaled = 0 ;
  186.                (void)sprintf(errbuf,
  187.                        "Font %s at %d not found; scaling %d instead.",
  188.                                          name, fd->dpi, lastresortsizes[j]) ;
  189.                error(errbuf) ;
  190.                lectureuser() ;
  191.                return 1 ;
  192.             }
  193.          }
  194.       }
  195.    }
  196.    (void)sprintf(name, "%s.%dpk", n, fd->dpi) ;
  197.    (void)sprintf(errbuf,
  198.       "Font %s%s not found, characters will be left blank.",
  199.       fd->area, name) ;
  200.    error(errbuf) ;
  201.    return(0) ;
  202. }
  203.  
  204. /*
  205.  *   Now our loadfont routine.  We return an integer indicating the
  206.  *   highest character code in the font, so we know how much space
  207.  *   to reserve for the character.  (It's returned in the font
  208.  *   structure, along with everything else.)
  209.  */
  210. void
  211. loadfont(curfnt)
  212.         register fontdesctype *curfnt ;
  213. {
  214.    register shalfword i ;
  215.    register shalfword cmd ;
  216.    register integer k ;
  217.    register integer length = 0 ;
  218.    register shalfword cc = 0 ;
  219.    register integer scaledsize = curfnt->scaledsize ;
  220.    register quarterword *tempr ;
  221.    register chardesctype *cd = 0 ;
  222.    int maxcc = 0 ;
  223.  
  224. /*
  225.  *   We clear out some pointers:
  226.  */
  227.    for (i=0; i<256; i++) {
  228.       curfnt->chardesc[i].TFMwidth = 0 ;
  229.       curfnt->chardesc[i].packptr = NULL ;
  230.       curfnt->chardesc[i].pixelwidth = 0 ;
  231.       curfnt->chardesc[i].flags = 0 ;
  232.    }
  233.    curfnt->maxchars = 256 ; /* just in case we return before the end */
  234.    if (!pkopen(curfnt)) {
  235.       tfmload(curfnt) ;
  236.       return ;
  237.    }
  238. #ifdef DEBUG
  239.    if (dd(D_FONTS))
  240.       (void)fprintf(stderr,"Loading pk font %s at %.1fpt\n",
  241.          name, (real)scaledsize/(alpha*0x100000)) ;
  242. #endif /* DEBUG */
  243.    if (pkbyte()!=247)
  244.       badpk("expected pre") ;
  245.    if (pkbyte()!=89)
  246.       badpk("wrong id byte") ;
  247.    for(i=pkbyte(); i>0; i--)
  248.       (void)pkbyte() ;
  249.    k = (integer)(alpha * (real)pkquad()) ;
  250.    if (k > curfnt->designsize + fsizetol ||
  251.        k < curfnt->designsize - fsizetol) {
  252.       (void)sprintf(errbuf,"Design size mismatch in font %s", name) ;
  253.       error(errbuf) ;
  254.    }
  255.    k = pkquad() ;
  256.    if (k && curfnt->checksum)
  257.       if (k!=curfnt->checksum) {
  258.          (void)sprintf(errbuf,"Checksum mismatch in font %s", name) ;
  259.          error(errbuf) ;
  260.        }
  261.    k = pkquad() ; /* assume that hppp is correct in the PK file */
  262.    k = pkquad() ; /* assume that vppp is correct in the PK file */
  263. /*
  264.  *   Now we get down to the serious business of reading character definitions.
  265.  */
  266.    while ((cmd=pkbyte())!=245) {
  267.       if (cmd < 240) {
  268.          switch (cmd & 7) {
  269. case 0: case 1: case 2: case 3:
  270.             length = (cmd & 7) * 256 + pkbyte() - 3 ;
  271.             cc = pkbyte() ;
  272.             cd = curfnt->chardesc+cc ;
  273.             if (nosmallchars || curfnt->dpi != curfnt->loadeddpi)
  274.                cd->flags |= BIGCHAR ;
  275.             cd->TFMwidth = scalewidth(pktrio(), scaledsize) ;
  276.             cd->pixelwidth = pkbyte() ;
  277.             break ;
  278. case 4: case 5: case 6:
  279.             length = (cmd & 3) * 65536 + pkbyte() * 256 ;
  280.             length = length + pkbyte() - 4 ;
  281.             cc = pkbyte() ;
  282.             cd = curfnt->chardesc+cc ;
  283.             cd->TFMwidth = scalewidth(pktrio(), scaledsize) ;
  284.             cd->flags |= BIGCHAR ;
  285.             i = pkbyte() ;
  286.             cd->pixelwidth = i * 256 + pkbyte() ;
  287.             break ;
  288. case 7:
  289.             length = pkquad() - 11 ;
  290.             cc = pkquad() ;
  291.             if (cc<0 || cc>255) badpk("character code out of range") ;
  292.             cd = curfnt->charde